package com.alibaba.otter.manager.web.valiadator;

import com.alibaba.otter.manager.web.utils.BeanValidator;
import com.alibaba.otter.manager.web.utils.ExpressEvaluators;
import com.alibaba.otter.manager.web.valiadator.annotation.OpGroup;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.util.Map;

public class ELGroupValidator implements ConstraintValidator<OpGroup, Object> {


    private OpGroup op;


    @Override
    public void initialize(OpGroup constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
        this.op = constraintAnnotation;
    }


    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {

        if (StringUtils.isBlank(op.el()) || ArrayUtils.isEmpty(op.opGroups())) {
            return true;
        }
        Map<String, Object> root = Map.of("o", value);
        CommonMethodRootObject rootObject = new CommonMethodRootObject(value.getClass());
        if (ExpressEvaluators.EVALUATOR.execute(op.el(), rootObject, root, Boolean.class)) {
            // 分组验证为空，默认按照表达式执行结果返回错误信息
            if (ArrayUtils.isEmpty(op.opGroups())) {
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate(op.message()).addConstraintViolation();
                return false;
            }
            // 执行可选分组验证
            String err = BeanValidator.validate(value, op.opGroups());
            if (StringUtils.isNotBlank(err)) {
                err = StringUtils.isBlank(op.message())? err : op.message();
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate(err).addConstraintViolation();
                return false;
            }
        }
        return true;
    }


    public record CommonMethodRootObject(Class<?> targetClass) {

    }
}
